#include "Self_Define_Functions.h"
using namespace std;
bool Compare_NewType( NewType data1, NewType data2 )
{
    return data1.data < data2.data;
}
void Sort_Population_Fitness(int *sorted_index, int *individual_rank, double *population_results, int population_size, NewType *sorted_data)
{
	
	int i, j;

	for (i = 0; i < population_size; ++i)
	{
		sorted_data[i].data = population_results[i];
		sorted_data[i].id = i;
	}
	sort( sorted_data, sorted_data+population_size, Compare_NewType );

	for (i = 0; i < population_size; ++i)
	{
		sorted_index[i] = sorted_data[i].id;
		individual_rank[sorted_data[i].id] = i;
	}
}


void Mutation_current_to_rand_1(double *population,double *mutation_vector, double *parent1, double *parent2, double *parent3, double *parent4, double Lbound, double Ubound, double F, int dim)
{
	int i;

	for (i = 0; i < dim; ++i)
	{
		mutation_vector[i] = parent1[i] + F * (parent2[i] - parent1[i]) + F * (parent3[i] - parent4[i]);

		if (mutation_vector[i] < Lbound)
			mutation_vector[i] = (Lbound+population[i])/2;
		if (mutation_vector[i] > Ubound)
			mutation_vector[i] = (Ubound+population[i])/2;
	}
}

void Mutation_rand_1(double *population,double *mutation_vector, double *parent1, double *parent2, double *parent3, double Lbound, double Ubound, double F, int dim)
{
	int i;

	for (i = 0; i < dim; ++i)
	{
		mutation_vector[i] = parent1[i] + F * (parent2[i] - parent3[i]);

		if (mutation_vector[i] < Lbound)
			mutation_vector[i] = (Lbound+population[i])/2;
		if (mutation_vector[i] > Ubound)
			mutation_vector[i] = (Ubound+population[i])/2;

	}
}

void Mutation_current_to_best_1(double *population,double *mutation_vector, double *parent1, double *parent2, double *parent3, double *parent4, double Lbound, double Ubound, double F, int dim)
{
	int i;

	for (i = 0; i < dim; ++i)
	{
		mutation_vector[i] = parent1[i] + F * (parent2[i] - parent1[i]) + F * (parent3[i] - parent4[i]);

		if (mutation_vector[i] < Lbound)
			mutation_vector[i] = (Lbound+population[i])/2;
		if (mutation_vector[i] > Ubound)
			mutation_vector[i] = (Ubound+population[i])/2;

	}
}
void Mutation_cur_pbest_1(double *population,double *mutation_vector,double *parent0, double *parent1, double *parent2, double *parent3, double Lbound, double Ubound, double F, int dim)
{
	int i;

	for (i = 0; i < dim; ++i)
	{
		mutation_vector[i] = parent0[i] + F * (parent1[i] - parent0[i]) + F * (parent2[i] - parent3[i]);

		if (mutation_vector[i] < Lbound)
			mutation_vector[i] = (Lbound+population[i])/2;
		if (mutation_vector[i] > Ubound)
			mutation_vector[i] = (Ubound+population[i])/2;

	}
}
void Mutation_cur_pbest_2(double *population,double *mutation_vector, double *parent0, double *parent1, double *parent2, double *parent3, double *parent4, double *parent5, double Lbound, double Ubound, double F, int dim)
{
	int i;

	for (i = 0; i < dim; ++i)
	{
		mutation_vector[i] = parent0[i] + F * (parent1[i] - parent0[i]) + F * (parent3[i] - parent2[i]) + F * (parent4[i] - parent5[i]);

		if (mutation_vector[i] < Lbound)
			mutation_vector[i] = (Lbound+population[i])/2;
		if (mutation_vector[i] > Ubound)
			mutation_vector[i] = (Ubound+population[i])/2;
	}
}
void Mutation_current_to_best_2(double *population,double *mutation_vector, double *parent1, double *parent2, double *parent3, double *parent4, double *parent5, double *parent6, double Lbound, double Ubound, double F, int dim)
{
	int i;

	for (i = 0; i < dim; ++i)
	{
		mutation_vector[i] = parent1[i] + F * (parent2[i] - parent1[i]) + F * (parent3[i] - parent4[i]) + F * (parent5[i] - parent6[i]);

		if (mutation_vector[i] < Lbound)
			mutation_vector[i] = (Lbound+population[i])/2;
		if (mutation_vector[i] > Ubound)
			mutation_vector[i] = (Ubound+population[i])/2;

	}
}
void Mutation_current_to_rand_2(double *population,double *mutation_vector, double *parent1, double *parent2, double *parent3, double *parent4, double *parent5, double *parent6, double Lbound, double Ubound, double F, int dim)
{
	int i;

	for (i = 0; i < dim; ++i)
	{
		mutation_vector[i] = parent1[i] + F * (parent2[i] - parent1[i]) + F * (parent3[i] - parent4[i]) + F * (parent5[i] - parent6[i]);
		if (mutation_vector[i] < Lbound)
			mutation_vector[i] = (Lbound+population[i])/2;
		if (mutation_vector[i] > Ubound)
			mutation_vector[i] = (Ubound+population[i])/2;

	}
}
void Mutation_rand_2(double *population,double *mutation_vector, double *parent1, double *parent2, double *parent3, double *parent4, double *parent5, double Lbound, double Ubound, double F, int dim)
{
	int i;

	for (i = 0; i < dim; ++i)
	{
		mutation_vector[i] = parent1[i] + F * (parent2[i] - parent3[i]) + F * (parent4[i] - parent5[i]);

		if (mutation_vector[i] < Lbound)
			mutation_vector[i] = (Lbound+population[i])/2;
		if (mutation_vector[i] > Ubound)
			mutation_vector[i] = (Ubound+population[i])/2;
	}
}
void Crossover(double *trial_vector, double *individual, double *mutation_vector, double CR, int dim)
{
	int i;

	boost::mt19937 generator(time(0)*rand());
	boost::uniform_int<> int_generator(0, dim - 1);
	boost::variate_generator< boost::mt19937&, boost::uniform_int<> > int_number(generator, int_generator);


	boost::uniform_real<> real_generator(0, 1);
	boost::variate_generator< boost::mt19937&, boost::uniform_real<> > real_number(generator, real_generator);

	int dim_rand = int_number();

	for (i = 0; i < dim; ++i)
	{
		if (i == dim_rand || real_number() <= CR)
			trial_vector[i] = mutation_vector[i];
		else
			trial_vector[i] = individual[i];
	}

}

int Roulette_Selection(double *probability, int population_size)
{
	int i, selected_index;

	boost::mt19937 generator(time(0)*rand());
	boost::uniform_real<> uniform_real_generate_r(0, 1);
	boost::variate_generator< boost::mt19937&, boost::uniform_real<> > random_real_num_r(generator, uniform_real_generate_r);//to generate a random number within [0,1]

	double random_pr = random_real_num_r();

	selected_index = -1;

	for (i = 0; i < population_size; ++i)
	{
		if (random_pr <= probability[i])
		{
			selected_index = i;
			break;
		}
	}

	return selected_index;

}